﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO.Ports;
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Threading;
using IPC.Communication.Framework.BasicFramework;
using IPC.Communication.Framework.Core.Net;

namespace IPC.Communication.Framework.Profinet.Omron
{
    public class OmronHostLinkServer : OmronFinsServer
    {
        private SerialPort serialPort;

        public byte UnitNumber
        {
            get;
            set;
        }

        public OmronHostLinkServer()
        {
            serialPort = new SerialPort();
        }

        //protected override void ThreadPoolLoginAfterClientCheck(Socket socket, IPEndPoint endPoint)
        //{
        //    AppSession appSession = new AppSession();
        //    appSession.IpEndPoint = endPoint;
        //    appSession.WorkSocket = socket;
        //    try
        //    {
        //        socket.BeginReceive(new byte[0], 0, 0, SocketFlags.None, SocketAsyncCallBack, appSession);
        //        AddClient(appSession);
        //    }
        //    catch
        //    {
        //        socket.Close();
        //        base.LogNet?.WriteDebug(ToString(), string.Format(StringResources.Language.ClientOfflineInfo, endPoint));
        //    }
        //}

        //[AsyncStateMachine(typeof(<SocketAsyncCallBack>d__6))]
        //[DebuggerStepThrough]
        //private void SocketAsyncCallBack(IAsyncResult ar)
        //{
        //    <SocketAsyncCallBack>d__6 stateMachine = new <SocketAsyncCallBack>d__6();
        //    stateMachine.<>t__builder = AsyncVoidMethodBuilder.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.ar = ar;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //}

        protected override byte[] PackCommand(int status, byte[] finsCore, byte[] data)
        {
            if (data == null)
            {
                data = new byte[0];
            }
            data = SoftBasic.BytesToAsciiBytes(data);
            byte[] array = new byte[27 + data.Length];
            Encoding.ASCII.GetBytes("@00FA0040000000").CopyTo(array, 0);
            Encoding.ASCII.GetBytes(UnitNumber.ToString("X2")).CopyTo(array, 1);
            if (data.Length != 0)
            {
                data.CopyTo(array, 23);
            }
            Encoding.ASCII.GetBytes(finsCore.SelectBegin(2).ToHexString()).CopyTo(array, 15);
            Encoding.ASCII.GetBytes(status.ToString("X4")).CopyTo(array, 19);
            int num = array[0];
            for (int i = 1; i < array.Length - 4; i++)
            {
                num ^= array[i];
            }
            SoftBasic.BuildAsciiBytesFrom((byte)num).CopyTo(array, array.Length - 4);
            array[array.Length - 2] = 42;
            array[array.Length - 1] = 13;
            return array;
        }

        public void StartSerial(string com)
        {
            StartSerial(com, 9600);
        }

        public void StartSerial(string com, int baudRate)
        {
            StartSerial(delegate(SerialPort sp)
            {
                sp.PortName = com;
                sp.BaudRate = baudRate;
                sp.DataBits = 7;
                sp.Parity = Parity.Even;
                sp.StopBits = StopBits.One;
            });
        }

        public void StartSerial(Action<SerialPort> inni)
        {
            if (!serialPort.IsOpen)
            {
                if (inni != null)
                {
                    inni.Invoke(serialPort);
                }
                serialPort.ReadBufferSize = 1024;
                serialPort.ReceivedBytesThreshold = 1;
                serialPort.Open();
                serialPort.DataReceived += SerialPort_DataReceived;
            }
        }

        public void CloseSerial()
        {
            if (serialPort.IsOpen)
            {
                serialPort.Close();
            }
        }

        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int num = 0;
            byte[] array = new byte[1024];
            int num2;
            do
            {
                Thread.Sleep(20);
                num2 = serialPort.Read(array, num, serialPort.BytesToRead);
                num += num2;
            }
            while (array[num - 1] != 13 && num2 != 0);
            if (num == 0)
            {
                return;
            }
            byte[] array2 = array.SelectBegin(num);
            if (array2.Length < 22)
            {
                if (base.LogNet != null)
                {
                    base.LogNet.WriteError(ToString(), "[" + serialPort.PortName + "] Uknown Data：" + array2.ToHexString(' '));
                }
            }
            else
            {
                if (base.LogNet != null)
                {
                    base.LogNet.WriteDebug(ToString(), "[" + serialPort.PortName + "] " + StringResources.Language.Receive + "：" + SoftBasic.GetAsciiStringRender(array2));
                }
                string @string = Encoding.ASCII.GetString(array2, 14, array2.Length - 18);
                byte[] array3 = ReadFromFinsCore(SoftBasic.HexStringToBytes(@string));
                if (array3 != null)
                {
                    serialPort.Write(array3, 0, array3.Length);
                    if (base.LogNet != null)
                    {
                        base.LogNet.WriteDebug(ToString(), "[" + serialPort.PortName + "] " + StringResources.Language.Send + "：" + SoftBasic.GetAsciiStringRender(array3));
                    }
                }
                RaiseDataReceived(sender, array2);
            }
        }

        public override string ToString()
        {
            return String.Format("OmronHostLinkServer[{0}]", base.Port);
        }
    }
}
